折腾用Alamofire去上传文件时,发现有两个参数:
name
filename
Alamofire.upload( .POST, ServerApi.uploadFileUrl(gCurUserItem.id), headers: curHeader, multipartFormData: {multipartFormData in multipartFormData.appendBodyPart( data: imageData, name: “file”, fileName: “image.jpg”, mimeType: “image/jpeg” ) }, |
这里到底该传入什么值,不清楚。
要去搞清楚。
multipartForm Data name filename
HTTP协议之multipart/form-data请求分析 – 像风一样的自由 – 博客频道 – CSDN.NET
multipart form-data boundary 说明 – yefeng – ITeye技术网站
<div–<—————————40612316912668 Content-Disposition: form-data; name=”c”; filename=”11 – 副本.txt” Content-Type: text/plain aaaa abbb cdd ccc <div–<—————————40612316912668 Content-Disposition: form-data; name=”d”; filename=”11.txt” Content-Type: text/plain |
Content-Disposition: form-data; name=”imageName”; filename=”imageName.png” Content-Type: image/png |
Under the hood: An HTTP request with multipart/form-data « Huy Nguyen
html – Example of multipart/form-data – Stack Overflow
请问如何用nodejs通过post发送multipart/form-data类型的http请求? – CNode技术社区
->
好像是:
name是针对于多个文件的时候才有用。
filename是当前文件名
-》那么估计是:
对于一次只上传单个文件的话,估计不用传递name了,只需要传递filename值应该就可以了。
-》
如果要传name的话,那么可以考虑写成:
name=“filenameNoSuffix”, filename=“fullFilename.suffix”
比如:
name=“20160625”,filename=“20160625.jpg”
后来再去看Alamofire的源码发现:
/** Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset. For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well and the w3 form documentation. – https://www.ietf.org/rfc/rfc2388.txt – https://www.ietf.org/rfc/rfc2045.txt – https://www.w3.org/TR/html401/interact/forms.html#h-17.13 */ public class MultipartFormData { /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`. public var contentType: String { get } /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries. public var contentLength: UInt64 { get } /// The boundary used to separate the body parts in the encoded form data. public let boundary: String /** Creates a multipart form data object. – returns: The multipart form data object. */ public init() /** Creates a body part from the data and appends it to the multipart form data object. The body part data will be encoded using the following format: – `Content-Disposition: form-data; name=#{name}` (HTTP Header) – Encoded data – Multipart form boundary – parameter data: The data to encode into the multipart form data. – parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. */ public func appendBodyPart(data data: NSData, name: String) /** Creates a body part from the data and appends it to the multipart form data object. The body part data will be encoded using the following format: – `Content-Disposition: form-data; name=#{name}` (HTTP Header) – `Content-Type: #{generated mimeType}` (HTTP Header) – Encoded data – Multipart form boundary – parameter data: The data to encode into the multipart form data. – parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. – parameter mimeType: The MIME type to associate with the data content type in the `Content-Type` HTTP header. */ public func appendBodyPart(data data: NSData, name: String, mimeType: String) /** Creates a body part from the data and appends it to the multipart form data object. The body part data will be encoded using the following format: – `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header) – `Content-Type: #{mimeType}` (HTTP Header) – Encoded file data – Multipart form boundary – parameter data: The data to encode into the multipart form data. – parameter name: The name to associate with the data in the `Content-Disposition` HTTP header. – parameter fileName: The filename to associate with the data in the `Content-Disposition` HTTP header. – parameter mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header. */ public func appendBodyPart(data data: NSData, name: String, fileName: String, mimeType: String) /** Creates a body part from the file and appends it to the multipart form data object. The body part data will be encoded using the following format: – `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header) – `Content-Type: #{generated mimeType}` (HTTP Header) – Encoded file data – Multipart form boundary The filename in the `Content-Disposition` HTTP header is generated from the last path component of the `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the system associated MIME type. – parameter fileURL: The URL of the file whose content will be encoded into the multipart form data. – parameter name: The name to associate with the file content in the `Content-Disposition` HTTP header. */ public func appendBodyPart(fileURL fileURL: NSURL, name: String) |
-》
很清楚了:
name和filename都应该传递
可以按照上述的总结,写成:
如果要传name的话,那么可以考虑写成:
name=“filenameNoSuffix”, filename=“fullFilename.suffix”
比如:
name=“20160625”,filename=“20160625.jpg”
然后,如果知道了文件的绝对路径,则可以用:
appendBodyPart(fileURL fileURL: NSURL, name: String)
其内部会自动帮你:
filename值为:文件路径中最后部分的文件名
根据文件路径最后的文件名的后缀,去计算出Content-Type的值
->后来经过调试,此处发现:
此处的name必须是”file”
然后filename可以指定别人值,比如”20160625_085958.jpg”
否则上传文件就出错:
response=SUCCESS: { errors = ( “The request body may not be null”, “The request body may not be null” ); } |
估计是:
服务器上传的接口设计就是:
-》必须传递file这个值
-》但是也不太应该是:
通过name指定file吧?
先不管,最后,能工作的结果是:
func uploadImageData(imageData:NSData){ dispatchBackground_async({ gLog.verbose(“imageData.length=\(imageData.length)”) self.pleaseWait() var curHeader = Dictionary<String, String>() curHeader[“authenticate”] = “token ” + gCurUserItem.accessToken gLog.verbose(“curHeader=\(curHeader)”) // let attachmentFilename = “image.jpg” let curDate = NSDate() /* let name = curDate.toString(“yyyyMMdd_hhmmss”) let filename = name + “.jpg” gLog.verbose(“name=\(name), filename=\(filename)”) -> response=SUCCESS: { errors = ( “The request body may not be null”, “The request body may not be null” ); } */ let name = “file” let filename = curDate.toString(“yyyyMMdd_hhmmss”) + “.jpg” gLog.verbose(“name=\(name), filename=\(filename)”) //uploadImageData > name=file, filename=20160625_085958.jpg Alamofire.upload( .POST, ServerApi.uploadFileUrl(gCurUserItem.id), headers: curHeader, multipartFormData: {multipartFormData in multipartFormData.appendBodyPart( data: imageData, name: name, fileName: filename, mimeType: “image/jpeg” ) }, encodingCompletion: { encodingResult in gLog.verbose(“encodingResult=\(encodingResult)”) /* encodingResult=Success($ curl -i \ -X POST \ -H “User-Agent: Sales App/com.qoro.QorosSalesApp (2016.6.24; OS ban ben 9.3(ban hao 13E230))” \ -H “authenticate: token fmc2q2m25vre0htehsijmlur53” \ -H “Content-Type: multipart/form-data; boundary=alamofire.boundary.5fd5efc56016a4df” \ -H “Accept-Encoding: gzip;q=1.0, compress;q=0.5” \ -H “Accept-Language: en-US;q=1.0, zh-Hans-US;q=0.9” \ “http://192.168.1.102:8080/app/user/10000010/upload”, false, nil) encodingResult=Success($ curl -i \ -X POST \ -H “User-Agent: Sales App/com.qoro.QorosSalesApp (2016.6.24; OS ban ben 9.3(ban hao 13E230))” \ -H “authenticate: token 4up3enr7nfd6c3rfei1ukcg1vv” \ -H “Content-Type: multipart/form-data; boundary=alamofire.boundary.01fc8db6b551cd51” \ -H “Accept-Encoding: gzip;q=1.0, compress;q=0.5” \ -H “Accept-Language: en-US;q=1.0, zh-Hans-US;q=0.9” \ “http://qapp.chinacloudapp.cn/app/user/10000010/upload”, false, nil) */ switch encodingResult { //case .Success(let uploadRequest, streamingFromDisk, streamFileURL): case .Success(let uploadRequest, _, _): // gLog.verbose(“uploadRequest=\(uploadRequest), streamingFromDisk=\(streamingFromDisk), streamFileURL=\(streamFileURL)”) gLog.verbose(“uploadRequest=\(uploadRequest)”) //upload=POST http://192.168.1.102:8080/app/user/10000010/upload //uploadRequest=POST http://qapp.chinacloudapp.cn/app/user/10000010/upload uploadRequest.responseJSON(completionHandler: { response in gLog.verbose(“response=\(response)”) /* response=SUCCESS: { code = 200; data = { created = 1466850689624; id = 1000001020160625103129624; location = “<null>”; name = “image.jpg”; owner = “<null>”; uploader = 10000010; }; message = ok; } response=SUCCESS: { errors = ( “The request body may not be null”, “The request body may not be null” ); } response=SUCCESS: { code = 200; data = { created = 1466859610413; id = 1000001020160625130010413; location = “<null>”; name = “20160625_085958.jpg”; owner = “<null>”; uploader = 10000010; }; message = ok; } */ switch response.result { case .Success(let value): let valueJson = JSON(value) gLog.verbose(“\(valueJson)”) /* { “message” : “ok”, “code” : 200, “data” : { “name” : “image.jpg”, “id” : “1000001020160625103129624”, “uploader” : 10000010, “location” : null, “created” : 1466850689624, “owner” : null } } */ let statusCode = valueJson[“code”].int ?? 0 if statusCode == 200 { let dataObj = valueJson[“data”].object let dataJson:JSON = JSON(dataObj) self.uploadAttachmentsHandler(Alamofire.Result.Success(dataJson)) gLog.verbose(“dataJson=\(dataJson)”) } else { self.noticeError(“上传附件出错”, autoClear: true, autoClearTime: 1) let message = valueJson[“message”].string ?? “” let messageStrArr = message.splitToStrArr(“|”) var messageStr:String = message var subCode:Int = 0 if messageStrArr.count > 1 { messageStr = messageStrArr[0] subCode = Int(messageStrArr[1]) ?? 0 } let error:NSError = NSError(domain: HttpErrorDomain, code: statusCode, userInfo: [ “message” : messageStr, “code” : statusCode, “subCode” : subCode, ]) self.uploadAttachmentsHandler(Alamofire.Result.Failure(error)) } case .Failure(let error): gLog.verbose(“error=\(error)”) self.uploadAttachmentsHandler(Alamofire.Result.Failure(error)) } }) case .Failure(let encodingError): gLog.error(“上传附件失败\(encodingError)”) } } ) }) } |
转载请注明:在路上 » [已解决]Alamofire中multipartFormData中的name和filename到底应该是什么值