private
func
selectHeadImage
(
)
{
let
imagePickerVC
=
TZImagePickerController
(
maxImagesCount
:
1
,
delegate
:
self
)
imagePickerVC
?
.
modalTransitionStyle
=
.
flipHorizontal
imagePickerVC
?
.
modalPresentationStyle
=
.
overCurrentContext
imagePickerVC
?
.
showSelectBtn
=
false
imagePickerVC
?
.
allowCrop
=
true
imagePickerVC
?
.
cropRect
=
CGRect
(
x
:
0
,
y
:
(
UIScreen
.
main
.
bounds
.
size
.
height
-
UIScreen
.
main
.
bounds
.
size
.
width
)
/
2.0
,
w
:
UIScreen
.
main
.
bounds
.
size
.
width
,
h
:
UIScreen
.
main
.
bounds
.
size
.
width
)
imagePickerVC
?
.
allowPickingVideo
=
false
imagePickerVC
?
.
allowPickingOriginalPhoto
=
false
imagePickerVC
?
.
didFinishPickingPhotosHandle
=
{
[
weak
self
]
photo
,
assets
,
isSelectOriginalPhoto
in
guard
let
photo
=
photo
,
let
this
=
self
,
photo
.
count
!=
0
else
{
return
}
let
img
=
photo
.
first
this
.
getUploadUrl
(
[
img
]
)
self
.
presentVC
(
imagePickerVC
!
)
获取图片上传路径数组,根据contentType数组后端返回一个上传路径的数组
HTTP Content-type 对照表:http://tools.jb51.net/table/http_content_type
接口返回:
"message": null,
"code": "00000",
"data": ["https://cps-oss-prod.oss-cn-hangzhou.aliyuncs.com/cps/2022/04/13/16498338964949632?OSSAccessKeyId=LTAI5tJKUNiuZCSTyvTjAoAd&Expires=1649837586&Signature=n8J4a6%2BwVk2QXs7agUMzXrs979o%3D"]
private
func
getUploadURL
(
_
imageArr
:
[
UIImage
]
)
{
var
typeArr
:
[
String
]
=
[
]
for
img
in
imageArr
{
if
let
data
=
img
.
jpegData
(
compressionQuality
:
1
)
{
let
type
=
data
.
getImageFormat
(
)
if
type
==
.
JPEG
{
typeArr
.
append
(
"image/jpeg"
)
}
else
if
type
==
.
PNG
{
typeArr
.
append
(
"image/png"
)
AlertHUD
.
show
(
)
var
params
:
[
String
:
Any
]
=
[
:
]
params
[
"contentType"
]
=
typeArr
JRNetworkManager
.
shared
.
request
(
CommonAPI
.
uploadUrl
(
params
)
,
completed
:
{
[
weak
self
]
(
result
)
in
AlertHUD
.
dismiss
(
withDelay
:
0.1
)
guard
let
this
=
self
else
{
return
}
if
let
pathArr
=
result
.
object
as
?
[
String
]
{
this
.
imagesUpload
(
imageArr
:
imageArr
,
pathArr
:
pathArr
,
contentTypeArr
:
typeArr
)
}
,
failed
:
{
(
status
,
error
)
in
AlertHUD
.
showText
(
error
)
private
func
imagesUpload
(
imageArr
:
[
UIImage
]
,
pathArr
:
[
String
]
,
contentTypeArr
:
[
String
]
)
{
if
imageArr
.
count
==
pathArr
.
count
||
imageArr
.
count
==
contentTypeArr
.
count
{
for
(
index
,
img
)
in
imageArr
.
enumerated
(
)
{
let
path
=
pathArr
[
index
]
JRNetworkManager
.
shared
.
aliyunUploadImage
(
img
,
path
,
completed
:
{
[
weak
self
]
(
result
)
in
if
let
photoPath
=
path
.
components
(
separatedBy
:
"?"
)
.
first
{
self
?
.
editAvatar
(
path
:
photoPath
)
}
,
failed
:
{
(
status
,
error
)
in
AlertHUD
.
showMsg
(
"操作失败"
)
private
func
editAvatar
(
path
:
String
)
{
Alamofire使用put方式上传图片到阿里云
import Foundation
import Alamofire
import SwiftyJSON
enum NetworkStatus : String {
case success = "00000"
case networkError = "A0001"
case otherError = "-1"
class JRNetworkManager: NSObject {
static let shared = JRNetworkManager()
typealias CompletedBlock = ((JSON) -> Void)
typealias FailedBlock = ((NetworkStatus, String) -> Void)
private override init() {
super.init()
func aliyunUploadImage(_ image: UIImage, _ url: String, completed: @escaping CompletedBlock, failed: @escaping FailedBlock) {
if let imageData = image.jpegData(compressionQuality: 0.5) {
let reURL = url
let stream = InputStream(data: imageData)
var uploadHeaders: HTTPHeaders = [:]
uploadHeaders["Content-Type"] = "image/jpeg"
do {
let newurl = try reURL.asURL()
upload(stream, to: newurl , method: .put,headers: uploadHeaders)
let tempData = JSON(["url":url])
completed(tempData)
} catch {
failed(.otherError, "上传失败")
} else {
failed(.otherError, "上传失败")
根据Data获取文件的contentType
import Foundation
enum ImageFormat {
case Unknow
case JPEG
case PNG
case GIF
case TIFF
case WebP
case HEIC
case HEIF
extension Data {
func getImageFormat() -> ImageFormat {
var buffer = [UInt8](repeating: 0, count: 1)
self.copyBytes(to: &buffer, count: 1)
switch buffer {
case [0xFF]: return .JPEG
case [0x89]: return .PNG
case [0x47]: return .GIF
case [0x49],[0x4D]: return .TIFF
case [0x52] where self.count >= 12:
if let str = String(data: self[0...11], encoding: .ascii), str.hasPrefix("RIFF"), str.hasSuffix("WEBP") {
return .WebP
case [0x00] where self.count >= 12:
if let str = String(data: self[8...11], encoding: .ascii) {
let HEICBitMaps = Set(["heic", "heis", "heix", "hevc", "hevx"])
if HEICBitMaps.contains(str) {
return .HEIC
let HEIFBitMaps = Set(["mif1", "msf1"])
if HEIFBitMaps.contains(str) {
return .HEIF
default: break;
return .Unknow
项目中导入SwiftyJSON和Alamofirepod ‘SwiftyJSON’, ‘4.0.0’pod ‘Alamofire’, ‘4.9.0’选择图片,获取上传路径列表import UIKitclass UserInfoController: UIViewController { /// 选择头像 private func selectHeadImage() { let imagePickerVC = TZImagePickerControll
RxAlamofire是包装,它围绕Swift 的优雅HTTP网络进行了。
将RxSwift包裹在Alamofire周围,使处理网络请求变得更加顺利和顺畅。 Alamofire是一个非常强大的框架,RxSwift添加了以简单有效的方式编写响应的功能。
一个基本用法是(考虑一个简单的货币转换器):
let formatter = NSNumberFormatter ()
formatter. numberStyle = . currencyStyle
formatter. currencyCode = " USD "
if let fromValue = NSNumberFormatter (). numberFromString ( self . fromTextField . text ! ) {
RxAlamofire. requestJSON (.
使用Alamofire上传图片到阿里OSS时会发现有的时候上传失败,原因是因为Alamofire拼接form-data的时候顺序会出错,所以需要自己使用URLRequest自己进行拼接就可以。
private let MultipartFormCRLF = "\r\n"
private let MutlipartFormCRLFData = MultipartFormCRLF.data(using...
IOS的Alamofire5.4高版本上传图片
Alamofire框架上传图片是比较冷门的知识。经常性报错,也找不到相关解释,或者其他低版本的写法,令开发者很是头疼。低版本的写法,在5.4.4API已经过期了。不在适用。我只用高版本的软件和最新软件。其他一概不用的。
那么5.4.4版本的Alamofire高版本的图片上传如何去写。我用springBoot后端去接受图片的上传的。swift是最新语法。把传入进来的图片转化成二进制。具体url是否传参,以及成功后是否搞一个回调函数通知调用者。自己完善一下。通过点
let image = UIImage(named: "xxx")
//将图片转化为JPEG类型的data 后面的参数是压缩比例
let jpegImage = UIImageJPEGRepresentation(image!, 0.5)
//要传的参数(比如我们带用户的加密uid)
let u...
上传调用方式如下:
OSSClient oss = new OSSClient(context, endpoint, credentialProvider, conf);
PutObjectResult putResult = oss.putO...
public IHttpActionResult Upload()
// return Ok(new ApiRequestResult { ErrorCode = 1, Data = 0, ErrorMessage = "Return result Is fasle" });
HttpFileC...
Package.swift 是在 Swift Package Manager 中使用的一个文件,它用来描述一个 Swift 包的元数据,包括包的名称、版本、依赖等信息。在使用 SPM 创建、管理和使用 Swift 包时,通常需要在项目目录中创建一个 Package.swift 文件。
一个简单的 Package.swift 文件可能包含如下内容:
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "MyPackage",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.watchOS(.v6),
.tvOS(.v13)
products: [
.library(
name: "MyPackage",
targets: ["MyPackage"]),
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "MyPackage",
dependencies: []),
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"]),
在 Package.swift 文件中配置完成后,使用 swift package 相关命令就可以管理这个包了, 如 swift package init, swift package update, swift package generate-xcodeproj等