You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							123 lines
						
					
					
						
							3.1 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							123 lines
						
					
					
						
							3.1 KiB
						
					
					
				| package command | |
| 
 | |
| import ( | |
| 	"context" | |
| 	"fmt" | |
| 	"net/url" | |
| 	"os" | |
| 	"strings" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/filer" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb" | |
| 	"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb" | |
| 	"github.com/seaweedfs/seaweedfs/weed/wdclient" | |
| 	"google.golang.org/grpc" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/security" | |
| 	"github.com/seaweedfs/seaweedfs/weed/util" | |
| ) | |
| 
 | |
| var ( | |
| 	filerCat FilerCatOptions | |
| ) | |
| 
 | |
| type FilerCatOptions struct { | |
| 	grpcDialOption grpc.DialOption | |
| 	filerAddress   pb.ServerAddress | |
| 	filerClient    filer_pb.SeaweedFilerClient | |
| 	output         *string | |
| } | |
| 
 | |
| func (fco *FilerCatOptions) GetLookupFileIdFunction() wdclient.LookupFileIdFunctionType { | |
| 	return func(ctx context.Context, fileId string) (targetUrls []string, err error) { | |
| 		vid := filer.VolumeId(fileId) | |
| 		resp, err := fco.filerClient.LookupVolume(ctx, &filer_pb.LookupVolumeRequest{ | |
| 			VolumeIds: []string{vid}, | |
| 		}) | |
| 		if err != nil { | |
| 			return nil, err | |
| 		} | |
| 		locations := resp.LocationsMap[vid] | |
| 		for _, loc := range locations.Locations { | |
| 			targetUrls = append(targetUrls, fmt.Sprintf("http://%s/%s", loc.Url, fileId)) | |
| 		} | |
| 		return | |
| 	} | |
| } | |
| 
 | |
| func init() { | |
| 	cmdFilerCat.Run = runFilerCat // break init cycle | |
| 	filerCat.output = cmdFilerCat.Flag.String("o", "", "write to file instead of stdout") | |
| } | |
| 
 | |
| var cmdFilerCat = &Command{ | |
| 	UsageLine: "filer.cat [-o <file>] http://localhost:8888/path/to/file", | |
| 	Short:     "copy one file to local", | |
| 	Long: `read one file to stdout or write to a file | |
|  | |
| `, | |
| } | |
| 
 | |
| func runFilerCat(cmd *Command, args []string) bool { | |
| 
 | |
| 	util.LoadSecurityConfiguration() | |
| 
 | |
| 	if len(args) == 0 { | |
| 		return false | |
| 	} | |
| 	filerSource := args[len(args)-1] | |
| 
 | |
| 	filerUrl, err := url.Parse(filerSource) | |
| 	if err != nil { | |
| 		fmt.Printf("The last argument should be a URL on filer: %v\n", err) | |
| 		return false | |
| 	} | |
| 	urlPath := filerUrl.Path | |
| 	if strings.HasSuffix(urlPath, "/") { | |
| 		fmt.Printf("The last argument should be a file: %v\n", err) | |
| 		return false | |
| 	} | |
| 
 | |
| 	filerCat.filerAddress = pb.ServerAddress(filerUrl.Host) | |
| 	filerCat.grpcDialOption = security.LoadClientTLS(util.GetViper(), "grpc.client") | |
| 
 | |
| 	dir, name := util.FullPath(urlPath).DirAndName() | |
| 
 | |
| 	writer := os.Stdout | |
| 	if *filerCat.output != "" { | |
| 
 | |
| 		fmt.Printf("saving %s to %s\n", filerSource, *filerCat.output) | |
| 
 | |
| 		f, err := os.OpenFile(*filerCat.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755) | |
| 		if err != nil { | |
| 			fmt.Printf("open file %s: %v\n", *filerCat.output, err) | |
| 			return false | |
| 		} | |
| 		defer f.Close() | |
| 		writer = f | |
| 	} | |
| 
 | |
| 	pb.WithFilerClient(false, util.RandomInt32(), filerCat.filerAddress, filerCat.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error { | |
| 
 | |
| 		request := &filer_pb.LookupDirectoryEntryRequest{ | |
| 			Name:      name, | |
| 			Directory: dir, | |
| 		} | |
| 		respLookupEntry, err := filer_pb.LookupEntry(context.Background(), client, request) | |
| 		if err != nil { | |
| 			return err | |
| 		} | |
| 
 | |
| 		if len(respLookupEntry.Entry.Content) > 0 { | |
| 			_, err = writer.Write(respLookupEntry.Entry.Content) | |
| 			return err | |
| 		} | |
| 
 | |
| 		filerCat.filerClient = client | |
| 
 | |
| 		return filer.StreamContent(&filerCat, writer, respLookupEntry.Entry.GetChunks(), 0, int64(filer.FileSize(respLookupEntry.Entry))) | |
| 
 | |
| 	}) | |
| 
 | |
| 	return true | |
| }
 |